package core

import (
	"fmt"
	"obc-go/tools"
	"sync"
	"time"
)

var (
	onceTimeCtrl sync.Once
	timeCtrl     *TimeCtrl
)

const (
	TimeSlotNum      = 16
	TimeSlotDuration = 1000000 / TimeSlotNum
)

type TimeSlot struct {
	SliceIndex uint8
	Msg        string
}

type TimeCtrl struct {
	ChanTimeSlices chan TimeSlot
	ChanQuit       chan struct{}
}

func GetTimeCtrl() *TimeCtrl {
	onceTimeCtrl.Do(func() {
		timeCtrl = &TimeCtrl{
			ChanTimeSlices: make(chan TimeSlot, TimeSlotNum),
		}
	})

	return timeCtrl
}

func (t *TimeCtrl) Start() {
	timer := time.Tick(TimeSlotDuration * time.Microsecond)
	var count uint8 = 0
	t.TimeSlots()
	defer close(t.ChanTimeSlices)
	defer close(t.ChanQuit)

loop:
	for {
		select {
		case <-timer:
			count = (count + 1) % TimeSlotNum
			msg := fmt.Sprintf("TimeSlice %d", count+1)
			t.ChanTimeSlices <- TimeSlot{SliceIndex: count + 1, Msg: msg}
		case <-t.ChanQuit:
			break loop
		}
	}
	fmt.Println("Time Slices On Board Stopped")
	return
}

func (t *TimeCtrl) Stop() {
	t.ChanQuit <- struct{}{}
}

func (t *TimeCtrl) TimeSlots() {
	tm := tools.NewTimeMeasure("Time Slices On Board", true)
	go func() {
		for {
			select {
			case timeSlot := <-t.ChanTimeSlices:
				tm.End()
				tm.Start()
				fmt.Println(timeSlot.Msg)
				c := GetTimeSlotActions()
				if a, OK := c.Actions[timeSlot.SliceIndex]; OK {
					a.Execute()
				}
			default:
			}
		}
	}()
}
